package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Api(tags = "菜品接口")
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    /**
     * 添加菜品信息
     * @return
     */
    @ApiOperation("添加菜品信息")
    @PostMapping
    public R save(@RequestBody DishDto dishDto) {
        log.info("dishDto = {}", dishDto);

        dishService.saveDishWithFlavors(dishDto);

        // 更新数据时，需要删除Redis中的数据
        // 方式一：添加菜品信息时，删除对应的数据
//        redisTemplate.delete("dish_" + dishDto.getCategoryId() + "_1");

        // 方式二：删除Redis中所有的数据
        Set<Object> keys = redisTemplate.keys("dish_*");
        if (CollectionUtils.isNotEmpty(keys)) {
            redisTemplate.delete(keys);
        }

        return R.success();
    }


    /**
     * 分页查询
     * @return
     */
    @ApiOperation("分页查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "页码", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageSize",value = "页面大小", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "name",value = "菜品名称", dataTypeClass = String.class)
    })
    @GetMapping("/page")
    public R<Page<DishDto>> page(@RequestParam(required = false,defaultValue = "1") Integer page,
                                 @RequestParam(required = false,defaultValue = "10") Integer pageSize,String name) {
        log.info("page = {}, pageSize = {}, name = {}",page,pageSize,name);

        // 1. 创建分页查询
        Page<Dish> pageInfo = new Page<>(page,pageSize);

        // 2. 拼接查询条件
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.like(StringUtils.isNotEmpty(name),Dish::getName,name);
        // 根据更新时间排序
        dishLambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);

        // 3. 执行分页查询
        dishService.page(pageInfo,dishLambdaQueryWrapper);

        // 完善数据，前端需要的是菜品的名称而不是菜品的id，需要将菜品的名称封装一下
        // 前端只需要两个数据  total和records
        Page<DishDto> dtoPage = new Page<>();
        dtoPage.setTotal(pageInfo.getTotal());

        List<Dish> pageList = pageInfo.getRecords();
        List<DishDto> dishDtoList = pageList.stream().map(dish -> {
            // 创建DishDto对象
            DishDto dishDto = new DishDto();
            // 使用工具类将一个对象拷贝到另一个对象
            BeanUtils.copyProperties(dish, dishDto);

            // 根据菜品分类id查询对应的菜品分类
            Category category = categoryService.getById(dish.getCategoryId());
            if (category != null) {
                dishDto.setCategoryName(category.getName());
            }
            return dishDto;
        }).collect(Collectors.toList());

        dtoPage.setRecords(dishDtoList);

        return R.success(dtoPage);
    }


    /**
     * 修改菜品时的数据回显
     * @return
     */
    @ApiOperation("修改菜品时的数据回显")
    @ApiImplicitParam(name = "id", value = "菜品id",dataTypeClass = Long.class)
    @GetMapping("/{id}")
    public R<DishDto> getById(@PathVariable Long id) {
        log.info("数据回显的id: {}", id);

        DishDto dishDto = dishService.getByIdWithFlavors(id);

        if (dishDto != null) {
            return R.success(dishDto);
        }
        return R.error("暂无数据!");
    }


    /**
     * 更新菜品数据
     * @param dishDto
     * @return
     */
    @ApiOperation("更新菜品数据")
    @PutMapping
    public R modify(@RequestBody DishDto dishDto) {
        log.info("dishDto = {}", dishDto);
        dishService.updateDishWithFlavors(dishDto);

        // 修改可能需要修改菜品的分类，这样会涉及多个分类下的数据，所以删除菜品对应的所有redis数据最简单
        // 修改数据成功需要，删除菜品对应所有的Redis数据
        Set<Object> keys = redisTemplate.keys("dish_*");
        if (CollectionUtils.isNotEmpty(keys)) {
            redisTemplate.delete(keys);
        }

        return R.success();
    }

    /**
     * 根据分类id查询对应的菜品信息
     * @param dish
     * @return
     */
    @ApiOperation("更新菜品数据")
    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish) {
        log.info("查询条件：dish = {}", dish);

        // 先查询Redis中的数据，如果有，之间返回
        String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();
        List<DishDto> dtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);
        if (CollectionUtils.isNotEmpty(dtoList)) {
            return R.success(dtoList);
        }


        // Redis中的数据没有，查询数据中
        // 1. 查询菜品信息数据
        LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
        // 只需要查询正在出售的菜品信息
        lambdaQueryWrapper.eq(Dish::getStatus, 1);
        lambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);

        List<Dish> dishList = dishService.list(lambdaQueryWrapper);

        // 判断查询的菜品是否有数据
        if (dishList != null && dishList.size() != 0) {

        }

        // 2. 查询菜品口味数据
        List<DishDto> dishDtoList = dishList.stream().map(dish1 -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish1, dishDto);

            // 查询菜品的口味数据
            LambdaQueryWrapper<DishFlavor> dishFlavorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishFlavorLambdaQueryWrapper.eq(DishFlavor::getDishId, dish1.getId());
            List<DishFlavor> dishFlavorList = dishFlavorService.list(dishFlavorLambdaQueryWrapper);

            dishDto.setFlavors(dishFlavorList);

            // 查询分类的名称
            Category category = categoryService.getById(dish1.getCategoryId());
            if (category != null) {
                dishDto.setCategoryName(category.getName());
            }
            return dishDto;
        }).collect(Collectors.toList());


        // 将数据库中的数据保存到Redis中
        redisTemplate.opsForValue().set(key, dishDtoList, 24, TimeUnit.HOURS);

        return R.success(dishDtoList);
    }


    /**
     * 根据id删除菜品信息
     * @param ids
     * @return
     */
    @ApiOperation("根据id删除菜品信息")
    @ApiImplicitParam(name = "ids",value = "菜品id列表",dataTypeClass = List.class)
    @DeleteMapping
    public R deleteByIds(@RequestParam List<Long> ids) {
        log.info("更具id删除菜品信息 ids = {}", ids);

        dishService.deleteDishWithFlavors(ids);


        // 删除数据时，只能删除停售的数据，停售的数据一定不会出现在Redis中，所以不需要删除redis中的数据
        /*Set<Object> keys = redisTemplate.keys("dish_*");
        if (CollectionUtils.isNotEmpty(keys)) {
            redisTemplate.delete(keys);
        }*/

        return R.success();
    }


    /**
     * 修改商品的状态
     * @return
     */
    @ApiOperation("修改商品的状态")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "status", value = "商品状态",dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "ids", value = "菜品id列表", dataTypeClass = List.class)
    })
    @PostMapping("/status/{status}")
    public R modifyByStatus(@PathVariable Integer status,@RequestParam List<Long> ids){
        log.info("修改的状态 status = {}；需要修改的数据 ids = {}", status, ids);

        dishService.updateByStatus(status, ids);

        // 停售/起售商品时，涉及到了数据的展示，需要清空商品对应的Redis数据
        Set<Object> keys = redisTemplate.keys("dish_*");
        if (CollectionUtils.isNotEmpty(keys)) {
            redisTemplate.delete(keys);
        }

        return R.success();
    }

}
